﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HITs
{
    class LatentSemanticAnalysis
    {
        static private float[,] MultiplyMatrix(float[,] matrixA, float[,] matrixB, int rowA, int columnA, int rowB, int columnB)
        {
            if (columnA == rowB)
            {
                float[,] result = new float[rowA, columnB];
                for (int i = 0; i < rowA; i++)
                    for (int j = 0; j < columnB; j++)
                        for (int k = 0; k < columnA; k++)
                            result[i, j] += matrixA[i, k] * matrixB[k, j];
                return result;
            }
            else
                return null;
        }

        static private float[,] TransformToIdentifyMatrix(float[] vector, int row, int column, bool LowRankApproximations, int NumberOfRemove)
        {
            if (row >= vector.Length && column >= vector.Length)
            {
                List<float> listfloat = new List<float>();
                listfloat.AddRange(vector);
                listfloat.Sort();

                if (LowRankApproximations == true)
                    for (int i = 0; i < NumberOfRemove; i++)
                        listfloat.RemoveAt(0);

                float[,] result = new float[row, column];
                for (int i = 0; i < listfloat.Count; i++)
                    result[i, i] = listfloat[listfloat.Count - 1 - i];

                return result;
            }
            else
                return null;
        }

        static private float[,] RemoveEmptyRowOfMatrix(float[,] matrix, ref int row, int column)
        {
            int i;
            bool flag;
            for (i = 0; i < row; i++)
            {
                flag = false;
                for (int j = 0; j < column; j++)
                    if (matrix[i, i] != 0.0d)
                    {
                        flag = true;
                        break;
                    }
                if (!flag)
                {
                    i++;
                    break;
                }
            }

            float[,] result = new float[i, column];
            for (int k = 0; k < i; k++)
                for (int j = 0; j < column; j++)
                    result[k, j] = matrix[k, j];
            row = i;
            return result;
        }

        static private double[,] ConvertFloatToDouble(float[,] matrix, int row, int column)
        {
            double[,] matrixtemp = new double[row, column];
            for (int i = 0; i < row; i++)
                for (int j = 0; j < column; j++)
                    matrixtemp[i, j] = matrix[i, j];
            return matrixtemp;
        }

        static public double[,] GetVT_SVD(float[,] matrix, int row, int column)
        {
            double[,] U, VT;
            double[] W;

            double[,] matrixTemp = ConvertFloatToDouble(matrix, row, column);
            alglib.rmatrixsvd(matrixTemp, row, column, 2, 2, 2, out W, out U, out VT);

            return VT;
        }

        static public float[,] GetVT_SVD(float[,] matrix, int row, int column, int NumberRowGet)
        {
            double[,] U, VT;
            double[] W;
            double[,] matrixTemp = ConvertFloatToDouble(matrix, row, column);
            alglib.rmatrixsvd(matrixTemp, row, column, 2, 2, 2, out W, out U, out VT);

            return GetLowApprociateRank(VT, column, NumberRowGet);
        }

        static public float[,] GetEuclidDistance(float[,] matrix, int row, int col)
        {
            float[,] result = new float[col, col];
            float euclidistance;

            for (int i = 0; i < col; i++)
                for (int j = i + 1; j < col; j++)
                {
                    euclidistance = 0.00f;
                    for (int k = 0; k < row; k++)
                        euclidistance += (float)Math.Pow(matrix[k, i] - matrix[k, j], 2);
                    result[i, j] = (float)Math.Round(Math.Sqrt(euclidistance), 2);
                    result[j, i] = result[i, j];
                }

            return result;
        }

        static public float[,] GetLowApprociateRank(double[,] matrix, int levelMatrix, int numberRowGet)
        {
            if (numberRowGet <= levelMatrix)
            {
                float[,] result = new float[numberRowGet, levelMatrix];
                for (int i = 0; i < numberRowGet; i++)
                    for (int j = 0; j < levelMatrix; j++)
                    {
                        result[i, j] = (float)Math.Round(matrix[i, j] * 1000, 0);
                    }
                return result;
            }
            else
                return null;
        }

        static public void SampleLSI()
        {
            double[,] matrixA = new double[11, 3];
            List<int> listMatrix = new List<int>();
            listMatrix.AddRange(new int[] {1,1,1,0,1,1,1,0,0,0,1,0,1,0,0
            ,1,0,1,1,1,1,1,1,1,1,0,1,0,2,0,0,1,1});
            float[] q = new float[] { 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 };

            for (int i = 0; i < 11; i++)
                for (int j = 0; j < 3; j++)
                    matrixA[i, j] = listMatrix[i * 3 + j];
            double[,] U, VT;
            double[] W;
            alglib.rmatrixsvd(matrixA, 11, 3, 2, 2, 2, out W, out U, out VT);


        }
    }
}
